#!/user/bin/env python3
# -*- coding: utf-8 -*-
"""
--------------------------------------
    Author:     JiChao_Song
    Date  :     2022/1/20 14:42
    Desc  :
--------------------------------------
"""
import json
import operator
import re
import urllib.request

from django.db import transaction
from tablib import Dataset

from common.enums.case_enums import CaseStatusEnum, CaseImportanceEnum
from common.exception.case import CaseImportHeadersExceptions, CaseImportCountExceptions
from common.utils.log_utils import logger
from common.utils.other_utils import get_enum_key_by_value
from person.dto.CaseImportDto import CaseImportDto, CaseImportListDto, CaseImportRealData
from person.models import CaseModule, Person, Project
from platform_auth.settings import BASE_DIR, YAML_TO_DICT


def read_case_import_file(project: int, filePath: str):
    headers = YAML_TO_DICT.get('server').get('caseImportFields').get('english')

    data = Dataset()
    fh = urllib.request.urlopen(url = filePath).read()
    data.load(fh, headers = True)
    data.headers = headers
    total = len(data.dict)
    failureCount = 0
    caseImportListDto = CaseImportListDto()

    caseImportRealList = []

    for i in range(len(data.dict)):
        n = dict(data.dict[i])

        caseStepDesc = n.get('caseStepDesc')
        caseStepResult = n.get('caseStepResult')
        caseVindicatorName = n.get('caseVindicatorName')
        caseModuleName_str: str = n.get('caseModuleName')

        # 保存原始备份
        caseImportRealData = CaseImportRealData()

        caseImportRealData.caseTitle = n.get('caseTitle')
        caseImportRealData.casePreCondition = n.get('casePreCondition')
        caseImportRealData.caseStepDesc = caseStepDesc
        caseImportRealData.caseStepDesc = caseStepResult
        caseImportRealData.caseStatus = n.get('caseStatus')
        caseImportRealData.caseImportance = n.get('caseImportance')
        caseImportRealData.remark = n.get('remark')

        # 创建用例对象
        caseImportDto = CaseImportDto()
        caseImportDto.rowId = i + 1
        caseImportDto.caseTitle = n.get('caseTitle')
        caseImportDto.casePreCondition = n.get('casePreCondition')
        caseImportDto.caseStatus = get_enum_key_by_value(
            enumObj = CaseStatusEnum, value = n.get('caseStatus'))
        caseImportDto.caseImportance = get_enum_key_by_value(enumObj = CaseImportanceEnum,
                                                             value = n.get('caseImportance'))
        caseImportDto.remark = n.get('remark')

        # 判断caseTitle， caseStatus， caseImportance比天线是否为空
        if caseImportDto.caseTitle is None or caseImportDto.caseTitle == '':
            caseImportDto.failureMsg.append('用例标题不能为空')
        if caseImportDto.caseStatus is None or caseImportDto.caseStatus == '':
            caseImportDto.failureMsg.append('用例状态不能为空')
        if caseImportDto.caseImportance is None or caseImportDto.caseImportance == '':
            caseImportDto.failureMsg.append('用例优先级不能为空')

        # 1.1 判断责任人是否存在
        if caseVindicatorName is None or caseVindicatorName == '':
            caseImportRealData.failureMsg.append('责任人不能为空')

        vindicator = Person.objects.filter(
            realName = caseVindicatorName, deleted = False)

        if vindicator.count() == 0:
            caseImportRealData.failureMsg.append(f'责任人:{caseVindicatorName}不存在')
            caseImportDto.caseVindicatorName = n.get('caseVindicatorName')
        else:
            caseImportDto.caseVindicatorName = vindicator.first().realName
            caseImportDto.caseVindicatorId = vindicator.first().id

        # 1.2 判断责任人是否为项目成员
        projects = Project.objects.filter(deleted = False, id = project).first()
        if projects.persons and projects.persons != '[]':
            persons = list(str(projects.persons[1:-1]).split(','))
            persons = list(map(int, persons))
            if int(vindicator.first().id) not in persons:
                caseImportRealData.failureMsg.append(f'当前项目不存在责任人:{caseVindicatorName}')
        else:
            caseImportRealData.failureMsg.append(f'当前项目不存在责任人:{caseVindicatorName}')

        # 用例步骤处理
        caseStepDesc_list = []
        if caseStepDesc:
            for i in str(caseStepDesc).split('\n'):
                caseStepDesc_list.append(
                    [i.split('.')[0].strip(), str(i.split('.')[1]).strip()])
        caseStepResult_list = []
        if caseStepResult:
            for i in str(caseStepResult).split('\n'):
                caseStepResult_list.append(
                    [i.split('.')[0].strip(), str(i.split('.')[1]).strip()])
        caseSteps = []
        for i in dict(caseStepDesc_list).keys():
            caseSteps.append(
                dict(
                    num = i,
                    desc = dict(caseStepDesc_list).get(i),
                    result = dict(caseStepResult_list).get(i)
                )
            )

        caseImportDto.caseSteps = json.dumps(caseSteps, ensure_ascii = False)

        # 模块处理
        caseModuleName = []
        if caseModuleName_str:
            caseModuleName = str(caseModuleName_str).split('/')[1:]
        caseModule = create_module_id(
            module_name_list = caseModuleName, project = project)
        if caseModule.get('failureMsg') and caseModule.get('id'):
            caseImportDto.failureMsg.append(caseModule.get('failureMsg'))
        caseImportDto.caseModuleId = caseModule.get('id')

        # 计算错误的数量
        if len(caseImportDto.failureMsg) != 0:
            failureCount += 1
            caseImportListDto.failureArray.append(caseImportRealData.__dict__)

        caseImportRealData.failureMsg = caseImportDto.failureMsg

        caseImportRealList.append(caseImportRealData.__dict__)
        caseImportListDto.array.append(caseImportDto.__dict__)

    caseImportListDto.total = total
    caseImportListDto.failureCount = failureCount
    caseImportListDto.successCount = total - failureCount

    # logger.error(caseImportRealList)
    return caseImportListDto.__dict__


def check_case_import_file(project: int, filePath: str):
    rel_headers = YAML_TO_DICT.get('server').get('caseImportFields').get('chinese')
    headers = YAML_TO_DICT.get('server').get('caseImportFields').get('english')
    data = Dataset()
    fh = urllib.request.urlopen(url = filePath).read()
    data.load(fh, headers = True)
    # 判断表头是否一致
    if not operator.eq(data.headers, rel_headers):
        raise CaseImportHeadersExceptions("导入模板格式错误")

    data.headers = headers
    total = len(data.dict)
    # 数量是否小于等于500
    if total > 501:
        raise CaseImportCountExceptions("导入数量不能超过500条")
    failureCount = 0
    caseImportListDto = CaseImportListDto()

    for i in range(len(data.dict)):
        n = dict(data.dict[i])

        caseStepDesc = n.get('caseStepDesc')
        caseStepResult = n.get('caseStepResult')
        caseVindicatorName = n.get('caseVindicatorName')
        caseModuleName_str: str = n.get('caseModuleName')

        # 保存原始备份
        caseImportRealData = CaseImportRealData()

        caseImportRealData.caseTitle = n.get('caseTitle')
        caseImportRealData.casePreCondition = n.get('casePreCondition')
        caseImportRealData.caseStepDesc = caseStepDesc
        caseImportRealData.caseStepResult = caseStepResult
        caseImportRealData.caseStatus = n.get('caseStatus')
        caseImportRealData.caseImportance = n.get('caseImportance')
        caseImportRealData.remark = n.get('remark')
        caseImportRealData.rowId = i + 1
        caseImportRealData.caseModuleName = caseModuleName_str
        caseImportRealData.caseVindicatorName = caseVindicatorName
        caseImportRealData.failureMsg = []
        # 判断caseTitle， caseStatus， caseImportance比天线是否为空
        if caseImportRealData.caseTitle is None or caseImportRealData.caseTitle == '':
            caseImportRealData.failureMsg.append('用例标题不能为空')
        if caseImportRealData.caseStatus is None or caseImportRealData.caseStatus == '':
            caseImportRealData.failureMsg.append('用例状态不能为空')
        if caseImportRealData.caseImportance is None or caseImportRealData.caseImportance == '':
            caseImportRealData.failureMsg.append('用例优先级不能为空')

        # 判断责任人是否存在
        if caseVindicatorName is None or caseVindicatorName == '':
            caseImportRealData.failureMsg.append('责任人不能为空')

        vindicator = Person.objects.filter(
            realName = caseVindicatorName, deleted = False)

        if vindicator.count() == 0:
            caseImportRealData.failureMsg.append(f'责任人:{caseVindicatorName}不存在')
        # 判断责任人是否为项目成员
        projects = Project.objects.filter(deleted = False, id = project).first()
        if projects.persons and projects.persons != '[]':
            persons = list(str(projects.persons[1:-1]).split(','))
            persons = list(map(int, persons))
            if int(vindicator.first().id) not in persons:
                caseImportRealData.failureMsg.append(f'当前项目不存在责任人:{caseVindicatorName}')
        else:
            caseImportRealData.failureMsg.append(f'当前项目不存在责任人:{caseVindicatorName}')

        # 模块处理
        caseModuleName = []
        if caseModuleName_str:
            caseModuleName = str(caseModuleName_str).split('/')[1:]
        if len(caseModuleName) > 5:
            caseImportRealData.failureMsg.append('模块层级最多支持5级')
        else:
            caseModule = check_module_id(
                module_name_list = caseModuleName, project = project)
            if caseModule.get('failureMsg'):
                caseImportRealData.failureMsg.append(caseModule.get('failureMsg'))

        # 计算错误的数量
        if len(caseImportRealData.failureMsg) != 0:
            failureCount += 1
            caseImportListDto.failureArray.append(caseImportRealData.__dict__)

        caseImportRealData.failureMsg = ''.join(f'{i};' for i in caseImportRealData.failureMsg)

        caseImportListDto.array.append(caseImportRealData.__dict__)

    caseImportListDto.total = total
    caseImportListDto.failureCount = failureCount
    caseImportListDto.successCount = total - failureCount

    # logger.error(caseImportRealList)
    return caseImportListDto.__dict__


def create_module_id(module_name_list: list, project: int):
    try:
        module_dict_list = []
        module_id_list = []
        data = module_name_list.copy()
        with transaction.atomic():
            for i in range(len(data)):
                if data.count(data[i]) != 1:
                    dat = dict(id = None, name = data[i],
                               failureMsg = '多级模块名称不能重复',
                               parent = None
                               )
                    module_dict_list.append(dat)
                    break
                queryset = CaseModule.objects.filter(
                    name = data[i], project = project, deleted = False)
                parent = module_id_list[i - 1] if i != 0 else None
                if queryset.count() != 0:
                    if queryset.first().parent != parent:
                        dat = dict(id = queryset.first().id, name = queryset.first().name,
                                   failureMsg = '所属模块已存在，且和上级模块不存在上下级关系,',
                                   parent = queryset.first().parent
                                   )
                        module_dict_list.append(dat)
                        break
                    else:
                        module_id_list.append(queryset.first().id)
                        module_dict_list.append(
                            dict(id = queryset.first().id, name = queryset.first().name, failureMsg = None,
                                 parent = queryset.first().parent)
                        )
                else:
                    # logger.error(data[i])
                    # logger.error(module_id_list)
                    caseModule = CaseModule.objects.create(
                        name = data[i],
                        project = project,
                        parent = parent
                    )
                    module_id_list.append(caseModule.id)
                    module_dict_list.append(
                        dict(id = caseModule.id, name = caseModule.name, failureMsg = None,
                             parent = caseModule.parent)
                    )
        return module_dict_list[-1]
    except Exception as e:

        logger.error(e)

        return {}


def check_module_id(module_name_list: list, project: int):
    try:
        module_dict_list = []
        module_id_list = []
        data = module_name_list.copy()
        with transaction.atomic():
            for i in range(len(data)):
                if data.count(data[i]) != 1:
                    dat = dict(id = 0, name = data[i],
                               failureMsg = '多级模块名称不能重复',
                               parent = None
                               )
                    module_dict_list.append(dat)
                    break
                queryset = CaseModule.objects.filter(
                    name = data[i], project = project, deleted = False)
                parent = module_id_list[i - 1] if i != 0 and len(module_id_list) >= 1 else None
                if queryset.count() != 0:
                    if queryset.first().parent != parent:
                        dat = dict(id = queryset.first().id, name = queryset.first().name,
                                   failureMsg = '所属模块已存在，且和上级模块不存在上下级关系,',
                                   parent = queryset.first().parent
                                   )
                        module_dict_list.append(dat)
                        break
                    else:
                        module_id_list.append(queryset.first().id)
                        module_dict_list.append(
                            dict(id = queryset.first().id, name = queryset.first().name, failureMsg = None,
                                 parent = queryset.first().parent)
                        )
        logger.debug(module_dict_list)
        return module_dict_list[-1]
    except Exception as e:

        logger.error(e)

        return {}
